Что такое controlled и uncontrolled компоненты в React?

JuniorReact · Frontend·Обновлено 15 сентября 2026
Коротко
Controlled-компонент хранит значение поля в state React и обновляет его через onChange, а uncontrolled — хранит значение в самом DOM, и доступ к нему получают через ref.

Что значит controlled и uncontrolled

В React элементы форм (input, textarea, select) могут работать в двух режимах — controlled (управляемый) и uncontrolled (неуправляемый). Разница в том, где находится «источник правды» (source of truth) для текущего значения поля.

  • Controlled — значение хранится в state компонента. Атрибут value элемента всегда равен значению из state, а изменения обрабатываются через onChange, который обновляет этот state.
  • Uncontrolled — значение хранится в самом DOM-узле, React не следит за ним напрямую. Чтобы прочитать значение, используется ref.

Controlled-компонент

function LoginForm() {
  // состояние хранит актуальное значение поля
  const [email, setEmail] = useState('');

  return (
    <input
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  );
}

Каждое нажатие клавиши вызывает onChange, обновляет state, и React перерисовывает input с новым value. Значение полностью контролируется React: если не обновить state, содержимое поля не изменится, даже если пользователь печатает.

Uncontrolled-компонент

function LoginForm() {
  const emailRef = useRef<HTMLInputElement>(null);

  const handleSubmit = () => {
    // читаем значение напрямую из DOM в момент отправки
    console.log(emailRef.current?.value);
  };

  return (
    <input type="email" ref={emailRef} defaultValue="" />
  );
}

Здесь React не хранит значение поля в state — оно живёт в DOM. defaultValue задаёт только начальное значение, а дальше браузер сам управляет содержимым инпута. Значение достаётся через ref только тогда, когда оно действительно нужно, например при сабмите формы.

Основные отличия

  • Controlled: value + onChange, uncontrolled: defaultValue/defaultChecked + ref.
  • Controlled даёт мгновенный доступ к значению на каждом рендере, uncontrolled — только по запросу через ref.
  • Controlled проще для валидации на лету, масок ввода, disabled-логики кнопок.
  • Uncontrolled требует меньше кода и меньше ре-рендеров, но хуже поддаётся программному управлению.
  • Для чекбоксов и радио аналогично: checked/onChange — controlled, defaultChecked — uncontrolled.
  • input type="file" всегда uncontrolled: значение файла нельзя задать программно из соображений безопасности, доступ к файлам возможен только через ref.

Когда что использовать

Controlled предпочтителен, когда нужна валидация «на лету», условное отключение кнопки отправки, форматирование ввода (маски) или синхронизация нескольких полей между собой. Uncontrolled уместен там, где важен минимальный boilerplate: простые формы без сложной логики, интеграция со сторонними DOM-библиотеками, а также для input type="file", который в принципе не может быть controlled.

В реальных проектах часто смешивают подходы: сложные поля делают controlled, а простые вспомогательные — uncontrolled, если их значение нужно только один раз, например при сабмите.

Что хочет услышать интервьюер

Понимание, что controlled-компонент хранит значение в state и вызывает re-render при каждом изменении

Знание, что uncontrolled-компонент хранит значение в DOM, а доступ к нему получают через ref

Умение написать пример кода для обоих подходов

Понимание разницы value/onChange vs defaultValue/defaultChecked

Знание, что input type="file" всегда uncontrolled

Пример: Controlled input

function LoginForm() {
  const [email, setEmail] = useState('');

  return (
    <input
      type="email"
      value={email}
      onChange={(e) => setEmail(e.target.value)}
    />
  );
}

Пример: Uncontrolled input

function LoginForm() {
  const emailRef = useRef<HTMLInputElement>(null);

  const handleSubmit = () => {
    console.log(emailRef.current?.value);
  };

  return <input type="email" ref={emailRef} defaultValue="" />;
}

Типичные ошибки

Указывают value без onChange, из-за чего React выводит предупреждение и поле становится read-only

Одновременно передают value и defaultValue одному элементу

Путают ref с state и пытаются читать значение uncontrolled-поля на каждом рендере

Считают uncontrolled-подход изначально плохой практикой, не понимая случаев его уместного использования

Забывают, что чекбоксы и радио используют checked/defaultChecked, а не value/defaultValue

Лучшие курсы по теме

изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Feature-Sliced Design

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее